#!/usr/bin/env sh

set -ex

function build_ffmpeg()
{
    echo "===== Building FFmpeg libraries on $1 ====="

    set +x
    export COMMON_FF_CFG_FLAGS=
    source buildscripts/ff_config_mac_lark.sh
    set -x

    [ -d extra/ffmpeg-$1 ] || mkdir extra/ffmpeg-$1

    cd extra/ffmpeg-$1

    export PKG_CONFIG_PATH=$PKG_CONFIG_PATH
    export PATH=$PKG_CONFIG_PATH:$PATH
    echo $PATH

    if [[ `uname -m` == $1 ]]; then
        FF_CROSS_BUILD=""
    else
        FF_CROSS_BUILD="--enable-cross-compile"
    fi

    echo "start configure"
    MACOSX_DEPLOYMENT_TARGET=10.10 
    $REPO/configure \
        --arch=$1 \
        --prefix=$REPO/build/ffmpeg-$1 \
        --extra-cflags="-arch $1 -target $1-apple-macos -mmacosx-version-min=10.10 -g" \
        --extra-ldflags="-target $1-apple-macos -mmacosx-version-min=10.10" \
        $FF_CROSS_BUILD \
        $COMMON_FF_CFG_FLAGS \

    make -j64
    make install

    cd -

    # delete symbolic files
    cd $REPO/build/ffmpeg-$1/lib
    for lib in `find *.dylib -type l`; do
        rm $lib
    done

    # change install_name with @rpath prefix
    for lib in `ls -1 *.dylib`; do
        name=$(otool -D $lib | grep -oE "lib[a-z0-9.]+dylib$" | grep -oE "lib[a-z0-9]+").dylib
        install_name_tool -id @rpath/$name $lib
        mv $lib $name
    done

    # change dependent libraries to new install_name
    for lib in `ls -1 *.dylib`; do
        for dep in $(otool -L $lib | grep -oE "^.+/ffmpeg-$1/lib/lib\S+\.dylib"); do
            name=$(echo $dep | grep -oE "lib[a-z0-9.]+dylib$" | grep -oE "lib[a-z0-9]+").dylib
            install_name_tool -change $dep @rpath/$name $lib
        done
    done

    cd -

    echo "===== Building FFmpeg libraries on $1 end ====="
}

function build_libffmpeg()
{
    echo "===== Building libFFmpeg on $1 ====="

    cd extra/ffmpeg-$1

    [ -d libffmpeg-$1 ] && rm -rf libffmpeg-$1 || echo
    mkdir libffmpeg-$1

    has_err=""

    clang -c \
    -arch $1\
    -target $1-apple-macos\
    -mmacosx-version-min=10.10 \
    -I . -I $REPO -I $REPO/libffmpeg \
    -L $REPO/build/ffmpeg-$1/lib \
    $REPO/libffmpeg/*.c \
    || has_err="YES"


    if [[ -n "$has_err" ]]; then
        echo "Error: failed to compile libffmpeg"
        cd -
        return -1
    fi

    ar -r libffmpeg.a $REPO/extra/ffmpeg-$1/*.o 
    mv libffmpeg.a $REPO/build/ffmpeg-$1/lib/
    # copy header file
    [ -d $REPO/build/ffmpeg-$1/include/libffmpeg ] || mkdir $REPO/build/ffmpeg-$1/include/libffmpeg
    cp $REPO/libffmpeg/ffmpeg_main.h $REPO/build/ffmpeg-$1/include/libffmpeg

    cd -

    echo "===== Building libFFmpeg on $1 end ====="
}

function build_ffmpeg_program()
{
    echo "===== Building FFmpeg Program on $1 ====="

    [ -d build/ffmpeg-$1/bin ] && rm -rf build/ffmpeg-$1/bin || echo
    mkdir build/ffmpeg-$1/bin

    cd extra/ffmpeg-$1

    stat=""

    clang -Wall -o $REPO/build/ffmpeg-$1/bin/ffmpeg \
        -mmacosx-version-min=10.10 \
        -arch $1\
        -target $1-apple-macos \
        -rpath @loader_path/../Frameworks \
        -I. -I../../ -I../../fftools/ \
        -L$REPO/buildscripts/build/thirdparty/mac/lib/ \
        -L../../build/ffmpeg-$1/lib \
        -ldav1d \
        -lavcodec \
        -lavdevice \
        -lavfilter \
        -lavformat \
        -lavutil \
        -lffmpeg \
        -lswresample \
        -lswscale \
        -lz -lbz2 -liconv \
        -framework AudioToolbox \
        -framework Cocoa \
        -framework CoreGraphics \
        -framework CoreImage \
        -framework OpenGL \
        -framework CoreMedia \
        -framework CoreVideo \
        -framework VideoToolbox \
        ../../fftools/cmdutils.c \
        ../../fftools/ffmpeg.c \
        ../../fftools/ffmpeg_filter.c \
        ../../fftools/ffmpeg_hw.c \
        ../../fftools/ffmpeg_opt.c \
        ../../fftools/ffmpeg_videotoolbox.c \
        || stat="Build Failed"
        
    if [[ -z "$stat" ]]; then
        echo "===== Building FFmpeg Program on $1 End ====="
        cd -
    else
        echo "===== Error: failed to compile ffmpeg program on $1 ====="
        cd -
        return -1
    fi
}

function install()
{
    echo "===== Installing ====="

    FIRST_ARCH=$(echo $1 | grep -oE "^[^;]+")
    ARCH_LIST=$(echo $1 | grep -Eo "[^;]+")
    HAS_ARM64=$(echo $ARCH_LIST | grep -o "arm64" || true)
    HAS_X86_64=$(echo $ARCH_LIST | grep -o "x86_64" || true)

    [ -d dist/mac ] && rm -rf dist/mac || echo
    mkdir -p dist/mac/bin dist/mac/ dist/mac/lib

    echo "===== Installing: Copy FFmpeg program ====="
    if [[ -n $HAS_ARM64 && -n $HAS_X86_64 ]]; then
        lipo build/ffmpeg-x86_64/bin/ffmpeg build/ffmpeg-arm64/bin/ffmpeg -create -output dist/mac/bin/ffmpeg
    else
        cp -v build/ffmpeg-$FIRST_ARCH/bin/ffmpeg dist/mac/bin/ffmpeg
    fi
    lipo -info dist/mac/bin/ffmpeg

    echo "===== Installing: Copy FFmpeg headers ====="
    cp -vR build/ffmpeg-$FIRST_ARCH/include dist/mac/

    echo "===== Installing: Copy FFmpeg internal headers ====="
    [ -d dist/mac/include/internal ] && rm -rf dist/mac/include/internal || echo

    mkdir -p dist/mac/include/internal
    cp extra/ffmpeg-$FIRST_ARCH/config.h dist/mac/include/internal
    if [[ -n $HAS_X86_64 ]]; then
        cp extra/ffmpeg-x86_64/config.h dist/mac/include/internal
    fi
    if [[ -n $HAS_ARM64 ]]; then
        mkdir -p dist/mac/include/internal/arm64
        cp extra/ffmpeg-arm64/config.h dist/mac/include/internal/arm64
    fi

    mkdir -p dist/mac/include/internal/libavcodec
    cp libavcodec/bytestream.h dist/mac/include/internal/libavcodec/bytestream.h
    cp libavcodec/h264.h dist/mac/include/internal/libavcodec/h264.h
    cp libavcodec/h2645_parse_ve.h dist/mac/include/internal/libavcodec/h2645_parse_ve.h
    cp libavcodec/vt_internal.h dist/mac/include/internal/libavcodec/vt_internal.h

    mkdir -p dist/mac/include/internal/libavformat
    cp libavformat/dv.h dist/mac/include/internal/libavformat/dv.h
    cp libavformat/internal.h dist/mac/include/internal/libavformat/internal.h
    cp libavformat/isom.h dist/mac/include/internal/libavformat/isom.h
    cp libavformat/os_support.h dist/mac/include/internal/libavformat/os_support.h

    mkdir -p dist/mac/include/internal/libavutil
    cp libavutil/reverse.h dist/mac/include/internal/libavutil/reverse.h

    echo "===== Installing: Copy dynamic libraries ====="
    #cp -vR buildscripts/build/thirdparty/mac/lib/*.dylib dist/mac/lib/
    if [[ -n $HAS_X86_64 ]]; then
        mkdir -p dist/mac/lib/x86_64
        cp build/ffmpeg-x86_64/lib/*.a dist/mac/lib/x86_64
    fi

    if [[ -n $HAS_ARM64 ]]; then
        mkdir -p dist/mac/lib/arm64
        cp build/ffmpeg-arm64/lib/*.a dist/mac/lib/arm64
    fi
    #echo "remove the unneeded library, such as the libavd1"
    #[ -e "dist/mac/lib/libdav1d.dylib" ] && rm dist/mac/lib/libdav1d.dylib
}

function generate_dsym_and_strip()
{
    echo "=============try to generate the dsym file and strip the dylibs"
    libpath=$1
    dsympath=$2
    mkdir -p $dsympath
    for file in ${libpath}/*
    do
        if test -f $file
        then
            dsymutil $file 
            strip -x -S $file $file
        fi
    done

    for file in ${libpath}/*.dSYM
    do
        mv $file $dsympath/
    done

    echo "=============generate the dsym file and strip the dylibs"
}

function merge_static2dylib_arch(){
    static_lib_path=$1
    ffmpeg_dist_path=$2
    min_version=$3
    arch=$4
    #the macosx_version_min should be 10.15 or newer, unless you want get an link error
 #   libtool -dynamic $static_lib_path/*.a  -o $ffmpeg_dist_path/libffmpeg.dylib \
 #   -macosx_version_min $min_version\
 #   -current_version 1.0.0\
 #   -compatibility_version 1.0.0 \
 #   -F$SDKROOT/System/Library/Frameworks \
 #   -framework VideoToolbox \
 #   -L$SDKROOT/usr/lib/ \
 #   -lobjc -lc -liconv -lz -lbz2\
 #   -framework CoreFoundation \
 #   -framework CoreVideo  \
 #   -framework CoreMedia \
 #   -framework AudioToolbox  \
 #   -framework CoreServices\
 #   -install_name @rpath/libffmpeg.dylib

    clang -dynamiclib $static_lib_path/*.a  -o $ffmpeg_dist_path/libffmpeg.dylib \
    -mmacosx-version-min=$min_version\
    -arch $arch \
    -target $arch-apple-macos\
    -all_load\
    -install_name @rpath/libffmpeg.dylib\
    -current_version 1.0.0\
    -compatibility_version 1.0.0 \
    -lobjc -lc -liconv -lz -lbz2\
    -framework VideoToolbox \
    -framework CoreFoundation \
    -framework CoreVideo  \
    -framework CoreMedia \
    -framework AudioToolbox  \
    -framework CoreServices
}

function merge_static2dylib(){
    if [[ -n $HAS_X86_64 ]]; then
        merge_static2dylib_arch dist/mac/lib/x86_64 dist/mac/lib/x86_64 10.10 x86_64
    fi

    if [[ -n $HAS_ARM64 ]]; then
        merge_static2dylib_arch dist/mac/lib/arm64 dist/mac/lib/arm64 10.15 arm64
    fi

    if [[ -n $HAS_ARM64 && -n $HAS_X86_64 ]]; then
        lipo dist/mac/lib/{x86_64,arm64}/libffmpeg.dylib -create -output dist/mac/lib/libffmpeg_ve.dylib
    elif [[ -n $HAS_X86_64 ]]; then
        cp dist/mac/lib/x86_64/libffmpeg.dylib dist/mac/lib/libffmpeg_ve.dylib
    elif [[ -n $HAS_ARM64 ]]; then
        cp dist/mac/lib/arm64/libffmpeg.dylib dist/mac/lib/libffmpeg_ve.dylib
    else
        echo "error arch"
    fi

    cd dist/mac/lib
    install_name_tool -id @rpath/libffmpeg_ve.dylib libffmpeg_ve.dylib
    dsymutil libffmpeg_ve.dylib
    strip -x -S libffmpeg_ve.dylib

    cd -
    
    if [[ -n $HAS_X86_64 ]]; then
        rm -rf dist/mac/lib/x86_64
    fi

    
    if [[ -n $HAS_ARM64 ]]; then
        rm -rf dist/mac/lib/arm64 
    fi


}

if [[ -z $1 ]]; then
    ARCH_LIST=`uname -m`  # use native arch by default
elif [[ $1 == "all" ]]; then
    ARCH_LIST="x86_64;arm64"
else
    ARCH_LIST=$1
fi

REPO=$(git rev-parse --show-toplevel)

for ARCH in $(echo $ARCH_LIST | grep -Eo "[^;]+"); do
    cd $REPO
    build_ffmpeg $ARCH  

    build_libffmpeg $ARCH  

    build_ffmpeg_program $ARCH  

    echo "===== Building $ARCH success. ====="
done

install $ARCH_LIST 

merge_static2dylib 

#generate_dsym_and_strip dist/mac/lib dist/mac/dsym

echo "===== Building ends, all success ====="
